"""
    Contains LookupController 
"""
import turbogears
import cherrypy
import genshi
import base64

from turbogears import expose, redirect
from turbogears.controllers import Controller
from turbogears.i18n.tg_gettext import lazystring

from mnemoply import mass_actions
from mnemoply.controllers import MassActions as mass_actions_controller

from mnemoply._renewed_lib.for_lookup import LocalMenu, LocalMenuItem,LookupData, \
                                LookupRequest, SQLObjectFieldLower, SQLPassthru, \
                                TableCol, VisibleColumns, TableLookupDataSource                                                   


import mnemoply._renewed_lib.widgets as widgets
from mnemoply._renewed_common_classes import MonthYear, Wrapper
from mnemoply._renewed_utils import urlparse_qs, get_by_key_and_delete
from mnemoply._renewed_constants import image_link

from mnemoply.model import UserFilter as UserFilter, File



from cherrypy import request, session


class LookupController(Controller, LocalMenu):
    """
        Table data lookup controller. With movable columns and row with links to objects.
    """


    lookup_columns = []
    filter_by_user = []
    mysql_view_name = ''
    is_editable = False
    is_addable = False
    is_showable = False
    is_deleteable = False
    controller_name = ''
    state = 'list'
    has_access = True
    search_model = None

    @classmethod
    def getName(cls):
        return cls.__name__.replace("Controller", "")
    
    def __init__(self, columns, default_order_by=None, mass_actions_class=None, title='',
                 default_order_asc=True, default_filters=None, mass_actions_class_names=None):

        if not default_filters: default_filters = {}
        Controller.__init__(self)
        LocalMenu.__init__(self)

        if not default_order_by:
            self.default_order_by = columns[0].name
        else:
            self.default_order_by = default_order_by
            
        self.default_order_asc = default_order_asc
        self.default_filters = default_filters

        self.columns = columns
        self.data_source = TableLookupDataSource(self.mysql_view_name)
        self.mass_actions_class = mass_actions_class
        self.mass_actions_class_names = mass_actions_class_names

        self.default_per_page = int(turbogears.config.get('lookup.per_page'))
        self.per_page_values = [20, 50, 100, 200, 500]
        self.max_data_len = int(turbogears.config.get('lookup.max_data_string_len'))

        self.title = title
        #
        #self.local_menu.append(self.create_menu_item('delete'))
        #self.local_menu.append(self.create_menu_item('lookup'))
        #self.local_menu.append(self.create_menu_item('lookup_add'))
        #self.local_menu.append(self.create_menu_item('edit'))
        #self.local_menu.append(self.create_menu_item('show'))
        #self.local_menu.append(self.create_menu_item('add'))
        #
        #self.object_local_menu.append(self.create_menu_item('edit',True))
        #self.object_local_menu.append(self.create_menu_item('show',True))
        #self.object_local_menu.append(self.create_menu_item('delete',True))
    
    def create_menu(self, state, for_row=False):
        menu =[]
        if not for_row:
            action_list=['delete','lookup','lookup_add','edit','show','add']
        else:
            action_list=['edit','show','delete']
        for action in action_list:
            if self.hasMenu(action, state, for_row):
                menu.append(self.create_menu_item(action))
        return menu

       
    def create_menu_item(self,action):
        res = LocalMenuItem(
            widget = widgets.ImageLink,
            params=image_link[action],
            )
        return res
     
    def hasMenu(self, action, state, for_row = False):
        where = for_row or (state in image_link[action+'_yes'])
        permission = self.hasAccess(state, action)
        if hasattr(self,'is_'+ action + 'able'):
            is_able = getattr(self,'is_'+ action + 'able')
        else:
            is_able = True
        return where and permission and is_able
    
    def hasAccess(self, state, action=''):
        if not action:
            action = state
        if action == 'lookup' or action == 'lookup_add' :
            action=''
        if turbogears.identity.in_group('dba'):
            return True
        prefix = '/'+self.controller_name+'/' if state else ''
        if turbogears.identity.has_any_permission(prefix + 'all', prefix+action):
            return True        
        else: 
            return False

    def checkAccess(self, state):
        if not self.hasAccess(state):
                url= turbogears.config.get( "identity.failure_url")
                raise turbogears.redirect(url)

    @expose()
    def save_list_args(self, **kw):
        """
            Update parameters for current controller in current session.
        """

        args = Wrapper(cherrypy.request.paramMap)
        # Load data from session
        data = LookupData(self)
        data.update(args)
        data.save()

        raise redirect('list')

    @expose()
    def save_filter(self, **kw):
        """
            Save user filter to current session.
        """

        args = Wrapper(cherrypy.request.paramMap)
        url = cherrypy.request.query_string

        user = turbogears.identity.current.user
        controller=self.__class__.__name__

        if args.name is not None:
            exist_filter = UserFilter.selectBy(user=user,
                                               controller=controller,
                                               name=args.name)

            if not len(list(exist_filter)):
                UserFilter(name=args.name,
                           url=url,
                           controller=controller,
                           user=user)
            else:
                exist_filter[0].url=url

        raise redirect('list')

    def select_filter(self):
        """
            Returns list of user filters for current user.
        """

        userfilters = UserFilter.selectBy(user=turbogears.identity.current.user,
                                          controller=self.__class__.__name__).orderBy('ordinal')
        return userfilters

    @expose()
    def load_filter(self, **kw):
        """
            Load selected filter to current session.
        """

        args = Wrapper(cherrypy.request.paramMap)

        if 'load_filter' in args:
            selected_filter = self.select_filter()[int(args.load_filter)]
            raise redirect('save_list_args?' + "tmp=" + selected_filter.url)

        raise redirect('list')

    @expose()
    def delete_filter(self, **kw):
        """
            Remove user filter from DB.
        """

        args = Wrapper(cherrypy.request.paramMap)

        if 'delete_filter' in args:
            selected_filter = self.select_filter()[int(args.delete_filter)]
            selected_filter.destroySelf()

        raise redirect('list')

    def get_filter_by_user(self, ):
        return turbogears. identity.current.user.get_filter_where_by_controller(self)
    
    
    def fill_lookup_data_defaults(self, data):
        """
            Try to create default user filter. If exists user.office or exists user filter returns True.
        """

        default_filter = list(self.select_filter())
        if len(default_filter):
            args = urlparse_qs("tmp=" + default_filter[0].url)
            data.update(args)
            return True
        exist_office = turbogears.identity.current.user.office
        if exist_office is None:
            return True
        return False

    def make_lookup_request(self, data):
        """
            Returns a request with filters and ordering parameters.
        """

        order_by = data.get('order_by', self.default_order_by)
        order_asc = data.get('order_asc', self.default_order_asc)
        filters = data.get('filters', self.default_filters)

        req = LookupRequest(filters=filters,
                            filter_by_user = self.get_filter_by_user(),
                            order_by=order_by,
                            order_asc=order_asc,
            )
        return req

    @expose()
    def list_rds(self):
        """
            Export data from lookup to RDS e.i. MS Excel file.
        """

        data = LookupData(self)
        req = self.make_lookup_request(data)
        visible_columns = VisibleColumns(session_data=data, lookup_controller=self)

        obj_records = self.data_source.getData(req)

        cherrypy.response.headerMap['Content-Disposition'] = \
            "filename=\"report-export-records.rds\""
        cherrypy.response.headerMap['Content-Type'] = "application/rds"

        vtemplate = File.byTag("ExportRecords")
        loader = genshi.template.loader.TemplateLoader('.')
        template = loader.load("mnemoply/_renewed_templates/lib/lookup_rds.html")

        return template.generate(**dict(
            records=obj_records,
            columns=visible_columns.cols,
            template_filename=vtemplate.name,
            template_data=base64.b64encode(vtemplate.content),
        )).render()


    def getMassActions(self): #TODO
        """
            Returns mass action list for this controller.
        """

        mass_actions_list = []
        if self.mass_actions_class is not None:
            mass_actions_list =  mass_actions.registry.getActionsForClass(self.mass_actions_class)
            if self.mass_actions_class_names is not None:
                mass_actions_list = [m for m in mass_actions.registry.getActionsForClass(self.mass_actions_class)
                    if m.__class__.__name__ in self.mass_actions_class_names]
        return mass_actions_list

    @expose(template="genshi:mnemoply._renewed_templates.lib.lookup")
    def list(self):
        """
            Render content.
        """
        state = 'lookup'
        local_menu=self.create_menu(state, False)
        object_local_menu=self.create_menu(state, True)
        self.checkAccess(state)
        # Load data from session
        data = LookupData(self)
        #if data.empty():
        self.fill_lookup_data_defaults(data)

        order_by = data.get('order_by', self.default_order_by)
        order_asc = data.get('order_asc', self.default_order_asc)
        per_page = data.get('per_page', self.default_per_page)
        filters = data.get('filters', self.default_filters)
        page_current = data.get('current_page', 1)
        visible_columns = VisibleColumns(session_data=data, lookup_controller=self)

        req = self.make_lookup_request(data)

        # Calc total
        total = self.data_source.getTotal(req)
        page_total = total/per_page + 1
        if total and (total % per_page == 0):
            page_total -= 1

        # Bound page_current
        if page_current < 1:
            page_current = 1
        if page_current > page_total:
            page_current = page_total

        # Get data
        start_from = (page_current - 1) * per_page
        obj_records = self.data_source.getData(req,
            start=start_from, end=start_from + per_page)

        records = []
        visible_columns_names = [col.name for col in visible_columns.cols]
        for orow in obj_records:
            row = [orow.id]
            for x in visible_columns_names:
                try:
                    value = getattr(orow, x)
                except KeyError:
                    continue

                if value is None:
                    value = ''
                else:
                    value = unicode(getattr(orow, x)).strip()

                # Trunc long lines
                if len(value) > self.max_data_len:
                    value = value[0:self.max_data_len] + '...'

                if not len(value):
                    value = None

                row.append(value)
            records.append(row)


        mass_actions = [ a for a in self.actions
                        if self.hasAccess('','%s/%s'%(self.controller_name, a.name)                                          )
                        ]
        

        # Render it
        return dict(
            title=self.title,
            columns=self.columns,
            data_source=self.data_source,
            per_page=per_page,
            mass_actions = mass_actions,
            show_actions=len(mass_actions),
            ma_form_values=MonthYear().get_next_month_year(),
            per_page_values=self.per_page_values,

            filters=filters,
            visible_columns=visible_columns.cols,
            order_by=order_by,
            order_asc=order_asc,
            records=records,
            page_total=page_total,
            page_current=page_current,
            total=total,

            local_menu=local_menu,
            object_local_menu=object_local_menu,

            user_filters=self.select_filter(),
        )
    @expose()
    def run_action(self, **kw):
        ma_name = get_by_key_and_delete('ma_name',kw)
        if ma_name:
            for (i,a) in enumerate( self.actions):
                if str(a.name) == ma_name:
                    return self.actions[i].show_params(**kw)

        turbogears.flash(_("Check fields"))
        raise turbogears.redirect('.')
    

    @expose()
    def index(self):
        """
            Default method. Redirect to /list/.
        """

        raise redirect("list")
